package org.example;

/**
 * Copyright (c) 2023-2033 All Rights Reserved
 *  wait() 和 notify()
 *
 * https://blog.csdn.net/x541211190/article/details/109258676
 * Thread0调用了wait()方法后，会释放掉对象锁并暂停执行后续代码，即从wait()方法之后到run()方法结束的代码，都将立即暂停执行，这就是wait()方法在线程中的作用。
 * CPU会将对象锁分配给一直等候的Thread1线程，Thread1执行了notify()方法后，会通知其他正在等待线程（Thread0）得到锁，但会继续执行完自己锁内的代码之后，才会交出锁的控制权。
 * 因为本例只有两个线程，所以系统会在Thread1交出对象锁控制权后（Synchronized代码块中代码全部执行完后），把锁的控制权给Thread0（若还有其他线程，谁得到锁是随机的，完全看CPU心情），Thread0会接着wait()之后的代码，继续执行到Synchronized代码块结束，将对象锁的控制权交还给CPU。
 *
 * @date: 2023/5/15
 */
public class ThreadWaitAndNotify {
    // 创建一个将被两个线程同时访问的共享对象
    public static Object object = new Object();

    // Thread0线程，执行wait()方法
    static class Thread0 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "初次获得对象锁，执行中，调用共享对象的wait()方法...");
                try {
                    // 共享对象wait方法，会让线程释放锁。
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "再次获得对象锁，执行结束");
            }
        }
    }

    // Thread1线程，执行notify()方法
    static class Thread1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                // 线程共享对象，通过notify()方法，释放锁并通知其他线程可以得到锁
                object.notify();
                System.out.println(Thread.currentThread().getName() + "获得对象锁，执行中，调用了共享对象的notify()方法");
            }
        }
    }

    // 主线程
    public static void main(String[] args) {
        Thread0 thread0 = new Thread0();
        Thread1 thread1 = new Thread1();
        thread0.start();
        try {
            // 保证线程Thread0中的wait()方法优先执行，再执线程Thread1的notify()方法
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread1.start();
    }

}
